﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EasierRdp.Models;

namespace EasierRdp.Util
{
    internal static class RdpContext
    {
        public static RdpRoot RdpRoot { get; set; }

        public static RdpSession FrontSession { get; set; }

        public static IDictionary<int, RdpServer> Servers;
        public static IDictionary<int, RdpUser> Users;
        public static IDictionary<int, RdpSession> Sessions;
        public static IDictionary<int, RdpSetting> Settings;

        public static void Initialize()
        {
            Servers = new Dictionary<int, RdpServer>();
            Users = new Dictionary<int, RdpUser>();
            Sessions = new Dictionary<int, RdpSession>();
            Settings = new Dictionary<int, RdpSetting>();
        }

        public static int AddServer(RdpServer item)
        {
            if (item.Id <= 0)
            {
                item.Id = Servers.Count == 0 ? 1 : Servers.Keys.Max() + 1;
                Servers.Add(item.Id, item);
            }
            else
            {
                Servers[item.Id] = item;
            }
            return item.Id;
        }

        public static void RemoveServer(RdpServer item)
        {
            if (Servers.ContainsKey(item.Id))
            {
                Servers.Remove(item.Id);
                foreach (var rdpUser in Users.Values)
                {
                    var newServers = rdpUser.Servers.Where(s => s.Ref != item).ToList();
                    rdpUser.Servers.Clear();
                    foreach (var rdpServerRef in newServers)
                    {
                        rdpUser.Servers.Add(rdpServerRef);
                    }
                }
                foreach (var group in RdpRoot.Groups)
                {
                    RemoveServerFromGroup(group, item);
                }
            }
        }

        public static int AddUser(RdpUser item)
        {
            if (item.Id <= 0)
            {
                item.Id = Users.Count == 0 ? 1 : Users.Keys.Max() + 1;
                Users.Add(item.Id, item);
            }
            else
            {
                Users[item.Id] = item;
            }
            return item.Id;
        }

        public static void RemoveUser(RdpUser item)
        {
            if (Users.ContainsKey(item.Id))
            {
                Users.Remove(item.Id);
                foreach (var server in Servers.Values)
                {
                    var newUsers = server.Users.Where(s => s.Ref != item).ToList();
                    server.Users.Clear();
                    foreach (var i in newUsers)
                    {
                        server.Users.Add(i);
                    }
                }
                foreach (var group in RdpRoot.Groups)
                {
                    RemoveUserFromGroup(group, item);
                }
            }
        }

        public static void RemoveSetting(RdpUser item)
        {
            if (Users.ContainsKey(item.Id))
            {
                Users.Remove(item.Id);
            }
        }

        public static int AddSession(RdpSession item)
        {
            if (item.Id <= 0)
            {
                item.Id = Sessions.Count == 0 ? 1 : Sessions.Keys.Max() + 1;
                Sessions.Add(item.Id, item);
            }
            else
            {
                Sessions[item.Id] = item;
            }
            return item.Id;
        }

        public static void RemoveSession(RdpSession item)
        {
            if (Sessions.ContainsKey(item.Id))
            {
                Sessions.Remove(item.Id);
            }
            if (FrontSession != null && item.Id == FrontSession.Id)
            {
                FrontSession = Sessions.Values.FirstOrDefault();
            }
        }

        public static int AddSetting(RdpSetting item)
        {
            if (item.Id <= 0)
            {
                item.Id = Settings.Count == 0 ? 1 : Settings.Keys.Max() + 1;
                Settings.Add(item.Id, item);
            }
            else
            {
                Settings[item.Id] = item;
            }
            return item.Id;
        }

        public static void RemoveSetting(RdpSetting item)
        {
            if (Settings.ContainsKey(item.Id))
            {
                Settings.Remove(item.Id);
            }
        }

        public static bool FindActive(RdpServer server)
        {
            return Sessions.Any(s => s.Value.Target == server);
        }

        public static bool FindActive(RdpUser user)
        {
            return Sessions.Any(s => s.Value.User == user);
        }

        public static bool FindRef(RdpServer server)
        {
            return Users.Any(user => user.Value.Servers.Any(s => s.Ref == server));
        }

        public static bool FindRef(RdpUser user)
        {
            return Servers.Any(server => server.Value.Users.Any(s => s.Ref == user));
        }

        private static void RemoveServerFromGroup(RdpGroup group, RdpServer server)
        {
            if(group.Servers.Contains(server))
            {
                group.Servers.Remove(server);
            }
            foreach (var sub in group.Groups)
            {
                RemoveServerFromGroup(sub, server);
            }
        }

        private static void RemoveUserFromGroup(RdpGroup group, RdpUser user)
        {
            if (group.Users.Contains(user))
            {
                group.Users.Remove(user);
            }
            foreach (var sub in group.Groups)
            {
                RemoveUserFromGroup(sub, user);
            }
        }
    }
}
